package rcs34.android.AndroidRC.Contacts;

import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import rcs34.android.AndroidRC.GApp;

import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.database.Cursor;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Note;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;

public class RawUpdateBatch {
  private ArrayList<ContentProviderOperation> batch;
  private String rawId;
  private JSONObject data;
  private HashMap<String, String> groupsCache = new HashMap<String, String>();
  private final String[] groupProjection = new String[] {
      ContactsContract.Groups.TITLE, ContactsContract.Groups._ID };

  public RawUpdateBatch(JSONObject _spec) {
    try {
      rawId = _spec.getString("rawId");
      data = _spec.getJSONObject("data");
      batch = new ArrayList<ContentProviderOperation>();
      addValueModification(StructuredName.CONTENT_ITEM_TYPE,
          ContactsContract.Data.DATA1, data.getString("name"));
      addValueModification(Nickname.CONTENT_ITEM_TYPE,
          ContactsContract.Data.DATA1, data.getString("nick"));
      addValueModification(Note.CONTENT_ITEM_TYPE, ContactsContract.Data.DATA1,
          data.getString("note"));
      addGroupsArrayModification(GroupMembership.CONTENT_ITEM_TYPE,
          ContactsContract.Data.DATA1, data.getJSONArray("groups"));
      addArrayModification(Email.CONTENT_ITEM_TYPE,
          ContactsContract.Data.DATA1, data.getJSONArray("emails"));
      addArrayModification(Phone.CONTENT_ITEM_TYPE,
          ContactsContract.Data.DATA1, data.getJSONArray("phones"));
      addArrayModification(StructuredPostal.CONTENT_ITEM_TYPE,
          ContactsContract.Data.DATA1, data.getJSONArray("postals"));
      addArrayModification(Event.CONTENT_ITEM_TYPE,
          ContactsContract.Data.DATA1, data.getJSONArray("events"));
    } catch (JSONException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

  private void addValueModification(String _mimetype, String _key, String _value) {
    // System.out.println(rawId+"|"+_mimetype+"|"+_key+"|"+_value);
    if (_value != null) {
      addDeleteOperation(_mimetype);
      addInsertOperation(_mimetype, _key, _value);
    }
  }

  private void addArrayModification(String _mimetype, String _key,
      JSONArray _array) {
    if (_array != null) {
      addDeleteOperation(_mimetype);
      if (_array.length() > 0) {
        for (int i = 0; i < _array.length(); i++) {
          try {
            addInsertOperation(_mimetype, _key, _array.getString(i));
          } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
      }
    }
  }

  private void addGroupsArrayModification(String _mimetype, String _key,
      JSONArray _array) {
    if (_array != null) {
      addDeleteOperation(_mimetype);
      if (_array.length() > 0) {
        groupsCache.clear();
        Cursor cursor = GApp.contentResolver.query(
            ContactsContract.Groups.CONTENT_URI, groupProjection, null, null,
            null);
        if (cursor != null && cursor.moveToFirst()) {
          while (!cursor.isAfterLast()) {
            groupsCache.put(cursor.getString(0), cursor.getString(1));
            cursor.moveToNext();
          }
        }
        cursor.close();
        for (int i = 0; i < _array.length(); i++) {
          try {
            addInsertOperation(_mimetype, _key,
                groupsCache.get(_array.getString(i)));
          } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
      }
    }
  }

  private void addDeleteOperation(String _mimetype) {
    ContentProviderOperation operation = ContentProviderOperation
        .newDelete(ContactsContract.Data.CONTENT_URI)
        .withSelection(
            ContactsContract.Data.MIMETYPE + "=? AND "
                + ContactsContract.Data.RAW_CONTACT_ID + "=?",
            new String[] { _mimetype, rawId }).build();
    batch.add(operation);
  }

  private void addInsertOperation(String _mimetype, String _key, String _value) {
    if (_value.length() > 0) {
      ContentValues values = new ContentValues();
      values.put(ContactsContract.Data.MIMETYPE, _mimetype);
      values.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
      values.put(_key, _value);
      ContentProviderOperation operation = ContentProviderOperation
          .newInsert(ContactsContract.Data.CONTENT_URI).withValues(values)
          .build();
      batch.add(operation);
    }
  }

  public ArrayList<ContentProviderOperation> getBatch() {
    return batch;
  }
}